/*
* @file_name: event.h
* @date: 2021/10/16
* @author: oaho
* Copyright @ hz oaho, All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef OAHO_EVENT_H
#define OAHO_EVENT_H
#include <memory>
#include <functional>
#ifdef __linux__
#define READ_FLAG  (EPOLLIN)
#define WRITE_FLAG (EPOLLOUT)
#define ERROR_FLAG (EPOLLERR)
#endif
class Event {
    friend class event_epoller;
    /*
     *  @param: fd
     *  @param: events
     */
public:
    using Ptr = std::shared_ptr<Event>;
    using func = std::function<void(const Event&)>;
public:
    Event(Event&&) = default;
    Event(const Event&) = delete;
    static Ptr     make_fd_event(int fd, typename Event::func&& r, typename Event::func&& w, typename Event::func&& e);
    static Ptr     make_basic_event(bool timer_task, size_t interval, bool run_once_flag, func&& f);
    inline int     fd() const { return _fd; }
    inline size_t  run_interval() { return interval; }
    inline bool    is_timer_task() const { return timer_task; }
    inline bool    run_once() const { return run_once_flag; }
    inline int     flags() const { return _flags; }
private:
    Event() = default;
    void operator()();
private:
    int     _fd{ -1 };
    int     _flags{ -1 };
    size_t  interval{ 0 };
    bool    timer_task{ false };
    bool    run_once_flag{ false };
    func    read_func;
    func    write_func;
    func    err_func;
};
typename Event::Ptr Event::make_fd_event(int fd, typename Event::func&& r, typename Event::func&& w, typename Event::func&& e) {
    std::shared_ptr<Event> ptr(new Event);
    auto& ev = *ptr;
    ev._fd = fd;
    ev.read_func = std::move(r);
    ev.write_func = std::move(w);
    ev.err_func = std::move(e);
    ev._flags = 0;
    if (ev.read_func)  ev._flags |= READ_FLAG;
    if (ev.write_func) ev._flags |= WRITE_FLAG;
    if (ev.err_func)   ev._flags |= ERROR_FLAG;
    return ptr;
}
typename Event::Ptr Event::make_basic_event(bool timer_task, size_t interval, bool run_once_flag, typename Event::func&& f){
    std::shared_ptr<Event> ptr(new Event);
    auto& ev = *ptr;
    ev.timer_task = timer_task;
    ev.interval = interval;
    ev.run_once_flag = run_once_flag;
    ev.read_func = std::move(f);
    return ptr;
}
/* for read-write-error event */
void Event::operator()()
{
    if (is_timer_task() && read_func) {
        read_func(*this);
        return;
    }
    if ((_flags & READ_FLAG) && read_func){
        read_func(*this);
    }
    if ((_flags & WRITE_FLAG) && write_func){
        write_func(*this);
    }
    if ((_flags & ERROR_FLAG) && err_func){
        err_func(*this);
    }
}
#endif